package app.server.project.core.tcp;

import app.server.project.core.exception.SysError;
import app.server.project.core.msgdispatcher.Dispatcher;
import app.server.project.core.tcp.model.*;
import app.server.project.core.token.TokenCache;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;

import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

@Component
@Slf4j
public class TcpSessionMgr {

    @Autowired
    private Dispatcher dispatcher;
    @Autowired
    private ApplicationEventPublisher publisher;
    @Autowired
    private TokenCache tokenCache;
    private ConcurrentHashMap<Long,ChannelHandlerContext> idMap=new ConcurrentHashMap<>();
    private ConcurrentHashMap<ChannelHandlerContext,Long> sessionMap=new ConcurrentHashMap<>();

    public void addSession(ChannelHandlerContext context, TcpReqModel tcpReqModel){
        LoginReq req= JSONUtil.toBean(tcpReqModel.getData(), LoginReq.class);
        if (StrUtil.isBlank(req.getToken())){
            log.info("登录错误,token为空");
            context.writeAndFlush(TcpRespModel.of(tcpReqModel.getCmd(), SysError.EmptyToken));
            context.close();
            return;
        }
        var cache=this.tokenCache.getToken(req.getId());
        log.info("缓存中的token:{}",cache);
        if (StrUtil.isBlank(cache)){
            context.writeAndFlush(TcpRespModel.of(tcpReqModel.getCmd(), SysError.Token));
            context.close();
            log.info("登录错误,缓存不存在此token");
            return;
        }
        if (!cache.equals(req.getToken())){
            log.info("登录错误,缓存中的token不相同");
            context.writeAndFlush(TcpRespModel.of(tcpReqModel.getCmd(), SysError.ErrorToken));
            context.close();
            return;
        }
        this.idMap.put(req.getId(), context);
        this.sessionMap.put(context, req.getId());
        this.publisher.publishEvent(TcpOnline.of(req.getId()));
    }

    public void doOffline(long id){
        var session=this.idMap.get(id);
        this.idMap.remove(id);
        if (Objects.isNull(session))return;
        this.sessionMap.remove(session);
        this.publisher.publishEvent(TcpOffline.of(id));
        this.sessionMap.remove(session);
        session.close();
        log.info("id:{},开始离线",id);
    }

    public Long getIdBySession(ChannelHandlerContext context){
        if (!this.sessionMap.containsKey(context))return null;
        var id=this.sessionMap.get(context);
        return id;
    }

    public void doExceptionClose(ChannelHandlerContext context){
        var id=this.sessionMap.get(context);
        if (Objects.isNull(id)){
            context.close();
            return;
        };
        this.doOffline(id);
    }

    public void push(long id,int cmd, Object data) {
        var pushUser=this.idMap.get(id);
        if (Objects.isNull(pushUser))return;
        pushUser.writeAndFlush(TcpRespModel.of(cmd,data));
    }
}
